package com.haixiaoke.saas.common.oss;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.aliyun.oss.ClientConfiguration;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.ObjectMetadata;
import com.haixiaoke.saas.common.config.OssConfig;
import com.haixiaoke.saas.common.exception.ServiceException;
import com.haixiaoke.saas.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.Base64Utils;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * @author qixi
 * @date 2023/9/22
 */
// @Service
@Component
@Slf4j
public class AliOssServiceImpl implements OssService {

    @Autowired
    private OssConfig ossConfig;

    /**
     * 为了实现同一个cos满足多个运行环境，所以在上传时自动在用户文件名称前加上当前的环境值，用于区分不同环境的上传文件。
     *
     * @param fileName 用户文件名称
     * @return 实际的cos上文件名称
     */
    private String getRealFileName(String saveFolder, String fileName) {
        String filePathPrefix = ossConfig.getApplicationName() + "/" + ossConfig.getProfileActive();
        return StringUtils.isNotEmpty(saveFolder) ? filePathPrefix + "/" + saveFolder + "/" + fileName : filePathPrefix + "/" + fileName;
    }

    /**
     * 往阿里云OSS上传一个文件
     * <a>https://help.aliyun.com/product/31815.html?spm=a2c4g.11186623.6.540.e45263287O4vS6</a>
     *
     * @param saveFolder    文件在oss上的路径，不传递时保存在默认的根路径下
     * @param contentType   文件类型，如：image/jpg
     * @param fileName      文件名称，如：a.jpg
     * @param contentLength 文件字节大小
     * @param input         输入流对象
     * @return
     */
    @Override
    public String upload(String saveFolder, String contentType, String fileName, long contentLength, InputStream input) {
        if (StringUtils.isEmpty(fileName) || StringUtils.isEmpty(contentType) || contentLength <= 0 || null == input) {
            return null;
        }
        ObjectMetadata objectMeta = new ObjectMetadata();
        objectMeta.setContentLength(contentLength);
        objectMeta.setContentType(contentType);
        String filePath = getRealFileName(saveFolder, fileName);
        try {
            OSSClient ossClient = new OSSClient(ossConfig.getOssEndpointUrl(), CredentialsProviderFactory.newDefaultCredentialProvider(ossConfig.getAccessKeyId(), ossConfig.getAccessKeySecret()), new ClientConfiguration());
            ossClient.putObject(ossConfig.getOssBucketName(), filePath, input);
            return "https://saas-v5." + ossConfig.getOssEndpointUrl() + "/" + filePath;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            try {
                input.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public String upload(String saveFolder, String fileMainName, MultipartFile multipartFile) {
        if (ObjectUtil.isEmpty(multipartFile)) {
            throw new ServiceException("文件为空!");
        }
        String filename = multipartFile.getOriginalFilename();
        String extFileName = "";
        if (StrUtil.isNotEmpty(filename)) {
            if (StrUtil.indexOf(filename, '.') != -1) {
                extFileName = filename.substring(filename.lastIndexOf("."));
            } else {
                String contentType = multipartFile.getContentType();
                // 根据文件类型判断文件后缀
                if (StrUtil.equals(contentType, MediaType.IMAGE_JPEG_VALUE)) {
                    extFileName = ".jpg";
                } else if (StrUtil.equals(contentType, MediaType.IMAGE_PNG_VALUE)) {
                    extFileName = ".png";
                } else if (StrUtil.equals(contentType, MediaType.IMAGE_GIF_VALUE)) {
                    extFileName = ".gif";
                } else {
                    extFileName = ".jpg";
                }
            }
        } else {
            throw new ServiceException("文件名为空!");
        }
        filename = fileMainName + extFileName;
        try {
            return upload(saveFolder, multipartFile.getContentType(), System.currentTimeMillis() + filename, multipartFile.getSize(), multipartFile.getInputStream());
        } catch (IOException e) {
            throw new ServiceException("上传文件失败! error:" + e.getMessage());
        }
    }

    @Override
    public String upload4SpecialName(String saveFolder, String fileName, MultipartFile multipartFile) {
        if (null != multipartFile && !multipartFile.isEmpty()) {
            try {
                return upload(saveFolder, multipartFile.getContentType(), fileName, multipartFile.getSize(), multipartFile.getInputStream());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    @Override
    public String uploadImgByBase64(String saveFolder, String fileName, String base64ImgContent) {
        if (StringUtils.isEmpty(fileName) || StringUtils.isEmpty(base64ImgContent)) {
            return null;
        }
        try {
            byte[] bytes = Base64Utils.decodeFromString(base64ImgContent);
            return upload(saveFolder, "image/jpg", fileName, bytes.length, new ByteArrayInputStream(bytes));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public void delete(String fileUrl) {
        if (StringUtils.isEmpty(fileUrl)) {
            return;
        }
        try {
            OSSClient ossClient = new OSSClient(ossConfig.getOssEndpointUrl(), CredentialsProviderFactory.newDefaultCredentialProvider(ossConfig.getAccessKeyId(), ossConfig.getAccessKeySecret()), new ClientConfiguration());
            ossClient.deleteObject(ossConfig.getOssBucketName(), fileUrl);
        } catch (OSSException | ClientException e) {
            e.printStackTrace();
        }
    }

    @Override
    public OSSObject getObject(String fileUrl) {
        if (StringUtils.isEmpty(fileUrl)) {
            return null;
        }
        try {
            OSSClient ossClient = new OSSClient(ossConfig.getOssEndpointUrl(), CredentialsProviderFactory.newDefaultCredentialProvider(ossConfig.getAccessKeyId(), ossConfig.getAccessKeySecret()), new ClientConfiguration());
            fileUrl = fileUrl.split(ossConfig.getOssEndpointUrl() + "/")[1];
            return ossClient.getObject(ossConfig.getOssBucketName(), fileUrl);
        } catch (OSSException | ClientException e) {
            log.info("获取oss文件异常:{}", e.getMessage(), e);
            return null;
        }
    }

    @Override
    public byte[] parseObject(OSSObject ossObject) {
        if (ObjectUtil.isEmpty(ossObject)) {
            throw new ServiceException("文件流为空");
        }
        try {
            InputStream inputStream = ossObject.getObjectContent();
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int length;
            while ((length = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, length);
            }
            outputStream.close();
            inputStream.close();
            return outputStream.toByteArray();
        } catch (Exception e) {
            log.info("格式化文件流异常：{}", e.getMessage(), e);
        }
        return null;
    }
}